package com.rwy.service;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import com.rwy.dao.StatisticsDaoMapper;
import com.rwy.dto.RespItemDTO;
import com.rwy.dto.StatisticDeviceDTO;
import com.rwy.dto.StatisticsSummaryDTO;
import com.rwy.util.CollectionUtil;
import com.rwy.util.PageInfo;
/* 统计服务*/
@Service
public class StatisticsSummaryService {

	@Autowired
	StatisticsDaoMapper statisticDao;


	public List<StatisticsSummaryDTO> getPrintKindStatistic(StatisticsSummaryDTO param) {
		Assert.notNull(param);
		Assert.notNull(param.getPartnerIDS());
		Assert.notNull(param.getKindType());
		List<StatisticsSummaryDTO> data = new ArrayList<>();
		switch (param.getKindType()) {
			case 1 :
				data = statisticDao.getPrintKindStatistic(param.getPartnerIDS(),param.getStartTime(), param.getEndTime(), StatisticsSummaryDTO.printKindMap.get(param.getKindType()), null);
				break;
			case 2 :
				data = statisticDao.getPrintKindStatistic(param.getPartnerIDS(),param.getStartTime(), param.getEndTime(), StatisticsSummaryDTO.printKindMap.get(param.getKindType()), null);
				break;
			case 3 :
				data = statisticDao.getPrintKindStatistic(param.getPartnerIDS(),param.getStartTime(), param.getEndTime(), StatisticsSummaryDTO.printKindMap.get(param.getKindType()), null);
				break;
			case 4 :
				data = statisticDao.getPrintKindStatistic(param.getPartnerIDS(),param.getStartTime(), param.getEndTime(), StatisticsSummaryDTO.printKindMap.get(param.getKindType()), null);
				break;
			case 5 :
				data = statisticDao.getPrintKindStatistic(param.getPartnerIDS(), param.getStartTime(), param.getEndTime(), null, StatisticsSummaryDTO.printKindMap.get(param.getKindType()));
				break;
			case 6 :
				data = statisticDao.getPrintKindStatistic(param.getPartnerIDS(), param.getStartTime(), param.getEndTime(), null, StatisticsSummaryDTO.printKindMap.get(param.getKindType()));
				break;
			case 7 :
				data = statisticDao.getTroubleTerminalStatistic(param.getPartnerIDS(),param.getStartTime(), param.getStartTime(), StatisticsSummaryDTO.printKindMap.get(param.getKindType()));
				break;
			case 8 :
				data = statisticDao.getOrderRefundItem(param.getPartnerIDS(), param.getStartTime(), param.getEndTime());
				break;
			case 9:
				data = statisticDao.getOrderRecord(param.getPartnerIDS(), param.getStartTime(), param.getEndTime());
				break;
			default :
				break;
		}
		assemKindStatisticList(data);
		return data;
	}

	public StatisticsSummaryDTO getStatisticSummary(StatisticsSummaryDTO param) {
		StatisticsSummaryDTO summary = statisticDao.getStatisticSummaryData(param.getPartnerIDS(),param.getStartTime(), param.getEndTime());
		Map<Integer, String> data = getPintKindSummary(summary.getCancePrintNum(), summary.getPrintSuccNum(),param.getStartTime(), param.getEndTime(),param.getPartnerIDS());
		
		return StatisticsSummaryDTO.builder().startTime(param.getStartTime()).endTime(param.getEndTime()).deviceCount(summary.getDeviceCount()).totalAmt(summary.getTotalAmt()).printSuccNum(summary.getPrintSuccNum()).cancePrintNum(summary.getCancePrintNum()).troubleDeviceNum(summary.getTroubleDeviceNum()).sheetCount(summary.getSheetCount()).r4Ratio(data.get(StatisticsSummaryDTO.print_kind_type_4R)).docRatio(data.get(StatisticsSummaryDTO.print_kind_type_document)).identRatio(data.get(StatisticsSummaryDTO.print_kind_type_ident)).provePhRatio(data.get(StatisticsSummaryDTO.print_kind_type_prove_photo)).refundAmt(summary.getRefundAmt()).build();
	}
	
	public PageInfo<StatisticDeviceDTO> getSaleNetworkStatisticList(StatisticDeviceDTO param) {
		Assert.notNull(param.getBusinessPartnerID());
		PageInfo<StatisticDeviceDTO> pageInfo = new PageInfo<>();
		List<StatisticDeviceDTO> list = new ArrayList<>();
		
		int total = statisticDao.getSaleNetworkTotal(param.getPartnerIDS());
		if (total > 0) {
			
			List<StatisticDeviceDTO> salesNetworks = statisticDao.getSaleNetworkStatisticPage(param.getPartnerIDS(),param.getStartTime(), param.getEndTime(), param.getPage(), param.getPageSize());
			List<StatisticDeviceDTO> source = statisticDao.getSaleNetworkRecordStatistic(param.getPartnerIDS(), param.getStartTime(), param.getEndTime(), salesNetworks);
			
			if (!CollectionUtil.isEmpty(source)) {
				Map<Integer, List<RespItemDTO>> data = new HashMap<>();
			
				List<RespItemDTO> temp = null;
				for (StatisticDeviceDTO tt : source) {
					if (tt.getTermimalID() == null)
						continue;

					if (data.containsKey(tt.getTermimalID())) {
						temp = data.get(tt.getTermimalID());
						temp.add(RespItemDTO.builder().itemID(tt.getPrintKindID()).itemName(StatisticsSummaryDTO.printKindDesc.get(tt.getPrintKindID())).itemCount(tt.getPrintCount()).build());
						data.put(tt.getTermimalID(), temp);
					} else {
						temp = new ArrayList<RespItemDTO>();
						temp.add(RespItemDTO.builder().itemID(tt.getPrintKindID()).itemName(StatisticsSummaryDTO.printKindDesc.get(tt.getPrintKindID())).itemCount(tt.getPrintCount()).build());
						data.put(tt.getTermimalID(), temp);
					}
				}
				for (Entry<Integer, List<RespItemDTO>> entry : data.entrySet()) {
					list.add(StatisticDeviceDTO.builder().termimalID(entry.getKey()).printCount(entry.getValue().stream().mapToInt(s -> s.getItemCount()).sum() ).list(entry.getValue()).build());
				}
				
			}
			fillHoleDevice(salesNetworks, list);
		}
		return pageInfo.assemPaInfo(param.getPage(), total, param.getPageSize(), list.parallelStream().sorted((a,b) -> {return b.getPrintCount().compareTo(a.getPrintCount());}).collect(Collectors.toList()));
	}
	
	/** 基于终端统计 */
	public PageInfo<StatisticDeviceDTO> getPrintRecordStatisticByTerminal(StatisticDeviceDTO param) {
		Assert.notNull(param.getBusinessPartnerID());
		PageInfo<StatisticDeviceDTO> pageInfo = new PageInfo<>();
		List<StatisticDeviceDTO> list = new ArrayList<>();
		int total = statisticDao.getTerminalTotal(param.getPartnerIDS());
		// 获取排序后的终端编号,先终端销量排序,然后再取值
		if (total > 0) {
			
			//Map<Integer, String> terminalName = new HashMap<>();
			
			List<StatisticDeviceDTO> devices = statisticDao.getTerminalPage(param.getPartnerIDS(),param.getStartTime(), param.getEndTime(), param.getPage(), param.getPageSize());
			List<StatisticDeviceDTO> source = statisticDao.getDevicePrintRecordStatistic(param.getPartnerIDS(), param.getStartTime(), param.getEndTime(), devices);

			if (!CollectionUtil.isEmpty(source)) {
				Map<Integer, List<RespItemDTO>> data = new HashMap<>();
			
				List<RespItemDTO> temp = null;
				for (StatisticDeviceDTO tt : source) {
					if (tt.getTermimalID() == null)
						continue;

					if (data.containsKey(tt.getTermimalID())) {
						temp = data.get(tt.getTermimalID());
						temp.add(RespItemDTO.builder().itemID(tt.getPrintKindID()).itemName(StatisticsSummaryDTO.printKindDesc.get(tt.getPrintKindID())).itemCount(tt.getPrintCount()).build());
						data.put(tt.getTermimalID(), temp);
					} else {
						temp = new ArrayList<RespItemDTO>();
						temp.add(RespItemDTO.builder().itemID(tt.getPrintKindID()).itemName(StatisticsSummaryDTO.printKindDesc.get(tt.getPrintKindID())).itemCount(tt.getPrintCount()).build());
						data.put(tt.getTermimalID(), temp);
					}
					//terminalName.putIfAbsent(tt.getTermimalID(), tt.getTerminalCode());
				}
				for (Entry<Integer, List<RespItemDTO>> entry : data.entrySet()) {
					list.add(StatisticDeviceDTO.builder().termimalID(entry.getKey()).list(entry.getValue()).build());
				}
				
			}
			fillHoleDevice(devices, list);
		}
		return pageInfo.assemPaInfo(param.getPage(), total, param.getPageSize(), list);
	}
	
	public List<RespItemDTO> getSalesNetworkRecordDetail(StatisticDeviceDTO param) {
		List<RespItemDTO> data = new ArrayList<>();
		Assert.notNull(param.getTermimalID());
		Assert.notNull(param.getBusinessPartnerID());
		List<StatisticDeviceDTO> source = statisticDao.getSaleNetworkRecordStatistic(param.getPartnerIDS(), param.getStartTime(), param.getEndTime(),Arrays.asList(StatisticDeviceDTO.builder().termimalID(param.getTermimalID()).build()));
		if (!CollectionUtil.isEmpty(source)) {
			for (StatisticDeviceDTO tt : source) {
				data.add(RespItemDTO.builder().itemID(tt.getPrintKindID()).itemName(StatisticsSummaryDTO.printKindDesc.get(tt.getPrintKindID())).itemCount(tt.getPrintCount()).build());
			}
		}
		if(data.size() == 0) {
			data.addAll(fillPrintKindData());
		}
		if(data.size() != 5) {
			fillPrintKindData(data);
		}
		return data;
	}
	
	@Deprecated
	public List<RespItemDTO> getDeviceRecordDetail(StatisticDeviceDTO param) {
		List<RespItemDTO> data = new ArrayList<>();
		Assert.notNull(param.getTermimalID());
		Assert.notNull(param.getBusinessPartnerID());
		List<StatisticDeviceDTO> source = statisticDao.getDevicePrintRecordStatistic(param.getPartnerIDS(), param.getStartTime(), param.getEndTime(),Arrays.asList(StatisticDeviceDTO.builder().termimalID(param.getTermimalID()).build()));
		if (!CollectionUtil.isEmpty(source)) {
			for (StatisticDeviceDTO tt : source) {
				data.add(RespItemDTO.builder().itemID(tt.getPrintKindID()).itemName(StatisticsSummaryDTO.printKindDesc.get(tt.getPrintKindID())).itemCount(tt.getPrintCount()).build());
			}
		}
		if(data.size() == 0) {
			data.addAll(fillPrintKindData());
		}
		if(data.size() != 5) {
			fillPrintKindData(data);
		}
		return data;
	}
	
	public List<RespItemDTO> getDeviceRecordChartByKindType(StatisticDeviceDTO param) {
		Assert.notNull(param.getTermimalID());
		Assert.notNull(StatisticsSummaryDTO.printKindMap.get(param.getType()));
		Assert.notNull(param.getBusinessPartnerID());
		List<RespItemDTO> item = statisticDao.getDeviceRecordByPrintKind(param.getPartnerIDS(), param.getStartTime(), param.getEndTime(), param.getTermimalID(), StatisticsSummaryDTO.printKindMap.get(param.getType()));
		replaceYearItemList(item);
		return item; 
	}
	
	public List<RespItemDTO> getSalesNetworkRecordChartByKindType(StatisticDeviceDTO param) {
		Assert.notNull(param.getTermimalID());
		Assert.notNull(StatisticsSummaryDTO.printKindMap.get(param.getType()));
		Assert.notNull(param.getBusinessPartnerID());
		List<RespItemDTO> item = statisticDao.getSalesNetworkRecordByPrintKind(param.getPartnerIDS(), param.getStartTime(), param.getEndTime(), param.getTermimalID(), StatisticsSummaryDTO.printKindMap.get(param.getType()));
		replaceYearItemList(item);
		return item; 
	}
	
    /**填补数据缺失的设备和数据类型不全数据*/
	private void fillHoleDevice(List<StatisticDeviceDTO> devices, List<StatisticDeviceDTO> list) {
		Map<Integer, String> terminalName = new HashMap<>();
		//添加设备数据
		List<StatisticDeviceDTO> temp = new ArrayList<>();
		for(StatisticDeviceDTO tt: devices) {
			terminalName.put(tt.getTermimalID(), tt.getSalesNetworkName());
		}
		Set<Integer> terminalSet = new HashSet<>();
		for(int i =0; i< list.size(); i++)  {
			terminalSet.add(list.get(i).getTermimalID());
		}
		//初始化没有数据的设备
		for(Integer key: terminalName.keySet()) {
			if(!terminalSet.contains(key)) {
				temp.add(StatisticDeviceDTO.builder().termimalID(key).salesNetworkName(terminalName.get(key)).printCount(0).list(fillPrintKindData()).build());
			}
		}
		
		//完善kind type data
		for (StatisticDeviceDTO tt: list) {
			tt.setSalesNetworkName(terminalName.get(tt.getTermimalID()));
			
			if(tt.getList()!= null && tt.getList().size() != 5) {
				fillPrintKindData(tt.getList());
			}
		}
		list.addAll(temp);
	}
	
	private void fillPrintKindData(List<RespItemDTO> item) {
		List<RespItemDTO> itemList = new ArrayList<>();
		for(Entry<Integer, String>  entry : StatisticsSummaryDTO.printKindDesc.entrySet()) {
			
			for(int i =0; i<item.size(); i++) {
				
				if(entry.getValue().equals(item.get(i).getItemName())) break;
				
				if(i ==(item.size() -1)) {
					itemList.add(RespItemDTO.builder().itemName(entry.getValue()).itemID(entry.getKey()).itemCount(0).build());
				}
			}
		}
		item.addAll(itemList);
	}
	
    private List<RespItemDTO> fillPrintKindData() {
    	List<RespItemDTO> itemList = new ArrayList<>();
		for(Entry<Integer, String>  entry : StatisticsSummaryDTO.printKindDesc.entrySet()) {
			itemList.add(RespItemDTO.builder().itemName(entry.getValue()).itemCount(0).itemID(entry.getKey()).build());
		}
		return itemList;
	}
	
	private Map<Integer, String> getPintKindSummary(Integer printFailNum, Integer printSuccNum, String startTime, String endTime, List<Integer> partnerIds) {
		Map<Integer, String> data = new HashMap<Integer, String>();
		List<StatisticsSummaryDTO> list = statisticDao.getPrintKindSummary(partnerIds,startTime, endTime);

		Predicate<List<StatisticsSummaryDTO>> predicate = CollectionUtil::isEmpty;
		Integer count = (printSuccNum+printFailNum); // 计算占比(分母为今天所有打印成功的数量+失败打印数量)
		if (predicate.negate().test(list)) {
			for (StatisticsSummaryDTO tt : list) {
				data.put(tt.getPrintKindId(), String.valueOf(tt.getTypeCount()));
				//count += tt.getTypeCount();
			}
		}
		for (Integer key : data.keySet()) {
			if (count == 0)
				break;
			data.put(key, formatDouble(((double) Integer.valueOf(data.get(key)) / count)*100));
		}
		checkPrintKindSummay(data);
		return data;
	}

	public static DecimalFormat df  = new DecimalFormat("0.#");
	
	private String formatDouble(double data){
		return df.format(data);
	}
	
	private void checkPrintKindSummay(Map<Integer, String> data) {
		data.putIfAbsent(StatisticsSummaryDTO.print_kind_type_4R, "0");
		data.putIfAbsent(StatisticsSummaryDTO.print_kind_type_document, "0");
		data.putIfAbsent(StatisticsSummaryDTO.print_kind_type_ident, "0");
		data.putIfAbsent(StatisticsSummaryDTO.print_kind_type_prove_photo, "0");
	}

	private void assemKindStatisticList(List<StatisticsSummaryDTO> data) {
		if (CollectionUtil.isEmpty(data))
			return;
		String[] arr = null;
		for (StatisticsSummaryDTO tt : data) {
			arr = tt.getTypeDate().split("-");
			tt.setTypeDate(arr[1] + "-" + arr[2]);
		}
	}
	
	private void replaceYearItemList(List<RespItemDTO> item) {
		if (CollectionUtil.isEmpty(item))
			return;
		String[] arr = null;
		for (RespItemDTO tt : item) {
			arr = tt.getItemName().split("-");
			tt.setItemName(arr[1] + "-" + arr[2]);
		}
	}
}
